package de.lulusoft.anothertorrent.gui.commands;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.HandlerEvent;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.commands.IHandlerListener;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;

import de.lulusoft.anothertorrent.core.servers.Server;
import de.lulusoft.anothertorrent.gui.AnotherTorrentGui;
import de.lulusoft.anothertorrent.gui.views.ServerView;

public class AddTorrentByUrlCommand implements IHandler, PropertyChangeListener {

	public static final String ID = "de.lulusoft.anothertorrent.gui.commands.AddTorrentByUrlCommand";
	
	private ArrayList<IHandlerListener> listeners = new ArrayList<IHandlerListener>();
	private boolean registeredWithServerView = false;
	private ServerView serverView = null;
	
	@Override
	public void addHandlerListener(IHandlerListener handlerListener) {
		listeners.add(handlerListener);
	}

	@Override
	public void dispose() {
		
	}

	@Override
	public Object execute(ExecutionEvent event) throws ExecutionException {
		System.out.println("AddTorrentByUrlCommand");
		
		IInputValidator urlValidator = new IInputValidator() {
		
			@Override
			public String isValid(String newText) {
				String validUrl = "^(https?://)"
			        + "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?" //user@
			        + "(([0-9]{1,3}\\.){3}[0-9]{1,3}" // IP- 199.194.52.184
			        + "|" // allows either IP or domain
			        + "([0-9a-z_!~*'()-]+\\.)*" // tertiary domain(s)- www.
			        + "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\." // second level domain
			        + "[a-z]{2,6})" // first level domain- .com or .museum
			        + "(:[0-9]{1,4})?" // port number- :80
			        + "((/?)|" // a slash isn't required if there is no file name
			        + "(/[0-9a-zA-Z_!~*'()\\.;?:@&=+$,%#-]+)+/?)$";
				Pattern p = Pattern.compile(validUrl,Pattern.DOTALL);
				Matcher m = p.matcher(newText);
				if (m.matches())
					return null;
				
				return "Not a valid URL";
			}
		};
		InputDialog inputUrl = new InputDialog(Display.getDefault().getActiveShell(), "Add Torrent by Url", "Enter the Torrent Url", "http://", urlValidator);
		
		inputUrl.setBlockOnOpen(true);
		if (inputUrl.open() == InputDialog.OK)
		{
			if (serverView  != null
					&& !serverView.getViewerSelection().isEmpty()
					&& serverView.getViewerSelection().getFirstElement() instanceof Server)
			{
				Server server = (Server)serverView.getViewerSelection().getFirstElement();
				try {
					server.getRTorrentManager().torrentAddByUrlAndStart(inputUrl.getValue());
				} catch (Exception e) {
					IStatus status = new Status(IStatus.ERROR, AnotherTorrentGui.PLUGIN_ID, "Could not add torrent", e);
					AnotherTorrentGui.getDefault().getLog().log(status );
					e.printStackTrace();
				}				
			}				
		}
		
		return null;
	}

	@Override
	public boolean isEnabled() {
		try 
		{
			if (serverView == null)
				serverView = (ServerView)PlatformUI.getWorkbench()
					.getActiveWorkbenchWindow().getActivePage().findView(ServerView.ID);
			if (!registeredWithServerView && serverView != null)
			{
				serverView.addPropertyChangeListener(this);
				registeredWithServerView = true;
			}
			
			if (serverView != null
					&& !serverView.getViewerSelection().isEmpty()
					&& serverView.getViewerSelection().getFirstElement()
					instanceof Server)
				return true;
		}catch (NullPointerException ne) {
			// ignore silently
		}catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	@Override
	public boolean isHandled() {
		return true;
	}

	@Override
	public void removeHandlerListener(IHandlerListener handlerListener) {
		listeners.remove(handlerListener);
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if (evt.getSource() instanceof ServerView
				&& evt.getPropertyName().equals(ServerView.P_SERVER))
		{
			for (IHandlerListener listener : listeners)
			{
				HandlerEvent handlerEvent = new HandlerEvent(this, true, false);
				listener.handlerChanged(handlerEvent );
			}
		}
	}

}
